﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Analytics.BusinessLogic;
using DiscoveryLogic.Analytics.BusinessLogic.Entities;
using DiscoveryLogic.Analytics.BusinessLogic.Importers;
using DiscoveryLogic.Analytics.BusinessLogic.Rules;
using DiscoveryLogic.Analytics.BusinessLogic.Searches;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.DataObjects.Rules;
using DiscoveryLogic.Analytics.DataObjects.Visuals;
using DiscoveryLogic.Common.Utilities;
using DiscoveryLogic.Common.Utilities.OpenXml;
using MessageBox=System.Windows.Forms.MessageBox;
using UserControl=System.Windows.Controls.UserControl;

namespace DiscoveryLogic.Analytics.Modules.DataImport
{
    /// <summary>
    /// Interaction logic for DataImportEditor.xaml
    /// </summary>
    public partial class DataImportEditor : UserControl
    {
        public delegate void OnEntityDataSetCreated(EntityDataSet entitySet);
        public event OnEntityDataSetCreated EntityDataSetCreated;

        private Dictionary<string, EntityImportRule> importRules;

        public DataImportEditor()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.cboImportRules.Items.Clear();
            this.importRules=new Dictionary<string, EntityImportRule>();
            List<RuleBase> rules =
                RuleManager.GetRulesByType(RuleType.Import, EntityIcons.ImportRuleIcon);
            if(rules !=null && rules.Count>0)
            {
                foreach(RuleBase rule in rules)
                {
                    this.importRules.Add(rule.RuleName, rule as EntityImportRule);
                }
            }
            
            if(this.importRules.Count>0)
            {
                foreach(string ruleName in this.importRules.Keys)
                {
                    this.cboImportRules.Items.Add(ruleName);
                }
            }

            this.cboEntityType.Items.Clear();
            foreach (EntityType entityType in Enum.GetValues(typeof(EntityType)))
                this.cboEntityType.Items.Add(entityType.ToString());
        }

        private void cboImportRules_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(this.cboImportRules.SelectedIndex>=0)
            {
                EntityImportRule rule = this.importRules[this.cboImportRules.SelectedItem.ToString()];
                this.txtDataSrcPath.Text = rule.DataSourcePath;
                this.txtSql.Text = rule.RecordListPath;
                
                if(rule.SrcDataFormat==SetDataSourceType.DB)
                {
                    this.txtSql.Visibility = System.Windows.Visibility.Visible;
                    this.cboRecordPath.Visibility = System.Windows.Visibility.Hidden;
                    this.lblRecordPath.Content = "SQL:";
                    this.lblDataSrcPath.Content = "Connection:";
                    string[] tblNames = DbUtil.GetTableNames(DataProviderType.MSSQL, string.Empty, rule.DataSourcePath);
                    if(tblNames !=null && tblNames.Length>0)
                    {
                        foreach (string tblName in tblNames)
                            this.cboRecordPath.Items.Add(tblName);
                    }
                    
                }
                else if (File.Exists(rule.DataSourcePath))
                {
                    this.txtSql.Visibility = System.Windows.Visibility.Hidden;
                    this.cboRecordPath.Visibility = System.Windows.Visibility.Visible;
                    if (rule.SrcDataFormat == SetDataSourceType.ExcelFile)
                    {
                        this.lblRecordPath.Content = "Worksheet:";
                        List<string> sheetNames = ExcelReader.GetWorksheetNames(rule.DataSourcePath);
                        if(sheetNames !=null && sheetNames.Count>0)
                        {
                            foreach(string sheetName in sheetNames)
                            {
                                this.cboRecordPath.Items.Add(sheetName);
                            }
                        }
                    }
                    else
                    {
                        this.lblRecordPath.Content = "Record path:";
                        List<string> xPaths = XmlDataUtil.GetDistinctElementPaths(rule.DataSourcePath);
                        foreach(string xPath in xPaths)
                        {
                            this.cboRecordPath.Items.Add(xPath);
                        }
                    }
                    this.lblDataSrcPath.Content = "File path:";
                }
                this.cboRecordPath.Text = rule.RecordListPath;

                this.lbSrcFields.Items.Clear();
                if(rule.EntityFieldSrcFieldMappings !=null && rule.EntityFieldSrcFieldMappings.Count>0)
                {
                    foreach(string srcField in rule.EntityFieldSrcFieldMappings.Values)
                    {
                        this.lbSrcFields.Items.Add(srcField);
                    }
                }
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            if(this.Parent is Window)
            {
                ((Window)this.Parent).Close();
            }
        }

        private void btnImport_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                EntityImportRule rule = this.importRules[this.cboImportRules.SelectedItem.ToString()];
                rule.DataSourcePath = this.txtDataSrcPath.Text;
                rule.RecordListPath = this.cboRecordPath.Text;
                if (rule.SrcDataFormat == SetDataSourceType.DB && !string.IsNullOrEmpty(this.txtSql.Text))
                    rule.RecordListPath = this.txtSql.Text;
                DataImportWorker worker = new DataImportWorker(
                    this.txtDataSetName.Text, rule, EntityIcons.ImportRuleIcon);
                EntityDataSet entitySet = worker.ImportData();
                if (entitySet != null && this.EntityDataSetCreated != null)
                    this.EntityDataSetCreated(entitySet);

                if (this.Parent is Window)
                {
                    ((Window)this.Parent).Close();
                }
            }
            catch(Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
                MessageBox.Show(ex.Message);
            }
            
        }

        private void btnBrowse_Click(object sender, RoutedEventArgs e)
        {
            if(this.cboImportRules.SelectedIndex>=0)
            {
                EntityImportRule rule = this.importRules[this.cboImportRules.SelectedItem.ToString()];
                switch(rule.SrcDataFormat)
                {
                    case SetDataSourceType.DB:
                        break;
                    case SetDataSourceType.ExcelFile:
                        OpenFileDialog dlg = new OpenFileDialog();
                        dlg.Filter = "Excel files(*.xls;*.xlsx)|*.xls;*.xlsx|All files(*.*)|*.*";
                        if(dlg.ShowDialog()==DialogResult.OK)
                            this.txtDataSrcPath.Text = dlg.FileName;
                        break;
                    case SetDataSourceType.XML:
                        OpenFileDialog dlg2 = new OpenFileDialog();
                        dlg2.Filter = "Xml files(*.xml;)|*.xml|All files(*.*)|*.*";
                        if (dlg2.ShowDialog() == DialogResult.OK)
                            this.txtDataSrcPath.Text = dlg2.FileName;
                        break;
                }
            }
        }

        private void btnImport2_Click(object sender, RoutedEventArgs e)
        {
            if(this.cboEntityType.SelectedIndex>=0 && !string.IsNullOrEmpty(this.txtKeys.Text))
            {
                EntityType entityType =
                    (EntityType)Enum.Parse(typeof(EntityType), this.cboEntityType.SelectedItem.ToString());
                List<string> keys=new List<string>();
                string[] items = this.txtKeys.Text.Split(new char[] {'\n', '\r'});
                foreach(string item in items)
                {
                    if(item.Trim().Length>0)
                        if(!keys.Contains(item.Trim()))
                            keys.Add(item.Trim());
                }
                List<EntityBase> entities=new List<EntityBase>();
                switch(entityType)
                {
                    case EntityType.Grants:
                        List<int> projIDs=new List<int>();
                        foreach(string key in keys)
                        {
                            projIDs.Add(int.Parse(key));
                        }
                        List<GrantDO> grants = GrantImportUtil.GetGrantsByProjectIDs(projIDs);
                        foreach(GrantDO grant in grants)
                            entities.Add(grant);
                        break;
                    case EntityType.Publications:
                        List<int> pmids=new List<int>();
                        foreach(string key in keys)
                            pmids.Add(int.Parse(key));
                        List<PublicationDO> pubs = PubImportUtil.GetPublicationsByPMID(pmids);
                        foreach(PublicationDO pub in pubs)
                            entities.Add(pub);
                        break;
                }
                string iconPath = EntityIcons.GetEntityIconByType(entityType);
                EntityDataSet entitySet = new EntityDataSet(this.txtDataSetName.Text, iconPath);
                entitySet.Entities = entities;
                entitySet.EntityType = entityType;
                entitySet.SourceType = SetDataSourceType.DB;
                entitySet.Save();
                MyData.ReadAllEntitySets();


                if (this.Parent is Window)
                {
                    ((Window)this.Parent).Close();
                }
            }
        }

        private void cboEntityType_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(this.cboEntityType.SelectedIndex>=0)
            {
                EntityType entityType =
                    (EntityType) Enum.Parse(typeof (EntityType), this.cboEntityType.SelectedItem.ToString());
                EntityBase entity = (EntityBase) Activator.CreateInstance(EntityTypeUtil.GetType(entityType));
                this.txtKeyField.Text = entity.IDField;
            }
        }
    }
}
